package view;

import controller.*;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;

import static view.ChatServer.links;

public class ChatClient {
    private final MessageController controller = new MessageController();
    private final GroupChatController groupChatController = new GroupChatController();
    private final GroupMessageController groupMessageController = new GroupMessageController();
    private final JTextPane textArea;
    private final JTextField textField;
    public static JButton btn_start;
    private final Charset charset = StandardCharsets.UTF_8;
    private final ByteBuffer buffer = ByteBuffer.allocate(1024);
    public SocketChannel _self;
    private Selector selector;
    private final DefaultListModel<String> fileModel;
    private final JTextArea fileTextArea;
    private final JList<String> jList;
    private final String username;
    private boolean flag = false;
    private String selectedValue;
    private final ChatClientController chatClientController = new ChatClientController();
    private final MainMessageController mainMessageController = new MainMessageController();
    private final DefaultListModel<String> model;
    private JTextPane currentTextArea;
    private final JPanel cardPanel;
    private final CardLayout cardLayout;
    private boolean flag1 = true;
    private boolean running = true;
    private final JList<String> myList;
    public static Map<String, Boolean> onlineUsers;
    private final DefaultListModel<String> groupModel;
    Thread thread;
    JFrame frame;
    private String fileSelectedValue;

    public ChatClient(String username) {
        this.username = username;
        String[] allGroupNames = groupChatController.getUserGroups(username);
        groupModel = new DefaultListModel<>();
        for (String groupName : allGroupNames) {
            groupModel.addElement(groupName);
        }
        JList<String> groupList = new JList<>(groupModel);
        onlineUsers = new HashMap<>();
        List<String> strings = chatClientController.selectUsers(username);
        model = new DefaultListModel<>();
        for (String s : strings) {
            model.addElement(s);
            onlineUsers.put(s, false);
        }
        myList = new JList<>(model);
        myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        frame = new JFrame(username);
        frame.setIconImage(Toolkit.getDefaultToolkit().createImage(ChatClient.class.getResource("qq.jpg")));
        textArea = new JTextPane();
        textArea.setEditable(false);
        textField = new JTextField();
        JButton addGroup = new JButton("加入群聊");
        JButton button1 = new JButton("添加好友");
        JButton btn_dispose=new JButton("退出群聊");
        JButton button2 = new JButton("刷新");
        JButton btn_send = new JButton("发送");
        btn_start = new JButton("连接");
        JButton btn_file = new JButton("文件");
        JButton btn_delete = new JButton("删除好友");
        JButton btn_clear = new JButton("取消选项");
        JPanel northPanel = new JPanel();
        northPanel.setLayout(new GridLayout(1, 7));
        northPanel.add(addGroup);
        northPanel.add(btn_dispose);
        northPanel.add(button1);
        northPanel.add(btn_delete);
        northPanel.add(btn_start);
        northPanel.add(button2);
        northPanel.setBorder(new TitledBorder("连接信息"));
        cardLayout = new CardLayout();
        cardPanel = new JPanel(cardLayout);
        JScrollPane rightScroll = new JScrollPane(textArea);
        rightScroll.setBorder(new TitledBorder("消息显示区"));
        cardPanel.add(rightScroll, "main");
        JPanel leftPanel = new JPanel(new BorderLayout());
        myList.setCellRenderer(new OnlineUserListCellRenderer());
        JScrollPane leftPanel1 = new JScrollPane(myList);
        JScrollPane leftPanel2 = new JScrollPane(groupList);
        leftPanel2.setBorder(new TitledBorder("群聊"));
        JPanel buttonPanel = new JPanel(new BorderLayout());
        JButton btn_flush = new JButton("刷新列表");
        buttonPanel.add(btn_flush, BorderLayout.NORTH);
        buttonPanel.add(btn_clear, BorderLayout.CENTER);
        JTextArea jTextArea = new JTextArea();
        jTextArea.setEditable(false);
        buttonPanel.add(jTextArea, BorderLayout.SOUTH);
        leftPanel.add(leftPanel1, BorderLayout.NORTH);
        leftPanel.add(leftPanel2, BorderLayout.CENTER);
        leftPanel.add(buttonPanel, BorderLayout.SOUTH);
        leftPanel1.setBorder(BorderFactory.createTitledBorder("好友"));
        JPanel southPanel = new JPanel(new BorderLayout());
        southPanel.add(textField, BorderLayout.CENTER);
        JPanel jPanel1 = new JPanel(new FlowLayout());
        jPanel1.add(btn_file);
        jPanel1.add(btn_send);
        southPanel.add(jPanel1, BorderLayout.EAST);
        southPanel.setBorder(new TitledBorder("写消息"));
        JSplitPane centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
                cardPanel);
        centerSplit.setDividerLocation(100);
        fileModel = new DefaultListModel<>();
        jList = new JList<>(fileModel);
        jList.setCellRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                label.setPreferredSize(new Dimension(200, label.getPreferredSize().height)); // 设置固定宽度 200
                return label;
            }
        });
        JPanel eastPanel = new JPanel(new BorderLayout());
        JScrollPane jScrollPane = new JScrollPane(jList);
        jScrollPane.setBorder(new TitledBorder("文件"));
        JPanel jPanel2 = new JPanel(new BorderLayout());
        fileTextArea = new JTextArea();
        fileTextArea.setEditable(false);
        fileTextArea.setLineWrap(true);
        JLabel jLabel = new JLabel("你选择的文件是：");
        JButton btn_config = new JButton("查看");
        jPanel2.add(jLabel, BorderLayout.NORTH);
        jPanel2.add(fileTextArea, BorderLayout.CENTER);
        jPanel2.add(btn_config, BorderLayout.SOUTH);
        eastPanel.add(jPanel2, BorderLayout.SOUTH);
        eastPanel.add(jScrollPane, BorderLayout.CENTER);
        frame.setLayout(new BorderLayout());
        frame.add(northPanel, BorderLayout.NORTH);
        frame.add(centerSplit, BorderLayout.CENTER);
        frame.add(eastPanel, BorderLayout.EAST);
        frame.add(southPanel, BorderLayout.SOUTH);
        frame.setSize(800, 600);
        int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
        int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
        frame.setLocation((screen_width - frame.getWidth()) / 2,
                (screen_height - frame.getHeight()) / 2);
        frame.setVisible(true);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                stopClient();
                flag1 = false;
                frame.dispose();
            }
        });
        jList.addListSelectionListener(e -> {
            fileSelectedValue = jList.getSelectedValue();
            fileTextArea.setText(fileSelectedValue);
        });
        btn_file.addActionListener(e -> {
            // 创建 JFileChooser 对象
            JFileChooser fileChooser = new JFileChooser();
            // 设置默认目录
            fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
            // 打开文件选择对话框
            int result = fileChooser.showOpenDialog(null);
            // 判断用户是否选择了一个文件
            if (result == JFileChooser.APPROVE_OPTION) {
                File selectedFile = fileChooser.getSelectedFile();
                String path = selectedFile.getAbsolutePath();
                JOptionPane.showMessageDialog(frame, "选择的文件: " + path);
                String string1 = String.valueOf(selectedFile);
                if (selectedValue == null) {
                    if (_self != null) {
                        sendMessage(string1 + ":" + "1");
                        textField.setText("");
                    } else {
                        JOptionPane.showMessageDialog(null, "用户未连接服务器，无法发送信息");
                    }
                }
                String string;
                if (selectedValue != null) {
                    if (groupModel.contains(selectedValue)) {
                        string = path.trim() + ":" + selectedValue + ":" + "group";
                    } else {
                        string = path.trim() + ":" + selectedValue;
                    }
                    if (_self != null) {
                        sendMessage(string);
                    } else {
                        JOptionPane.showMessageDialog(null, "用户未连接服务器，无法发送信息");
                    }
                }
            } else {
                JOptionPane.showMessageDialog(frame, "未选择文件");
            }
            updateFileList();
        });
        btn_dispose.addActionListener(e->{
            DisposeGroupView disposeGroupView=new DisposeGroupView(username);
            disposeGroupView.showUi();
        });
        btn_clear.addActionListener(e -> {
            if (selectedValue != null) {
                selectedValue = null;
                cardLayout.show(cardPanel, "main");
                jTextArea.setText(null);
                updateUserList();
                updateGroupList();
            }
        });
        addGroup.addActionListener(e -> {
            AddGroupView addGroupView = new AddGroupView(username);
            addGroupView.showUi();
        });
        if (currentTextArea != null) {
            currentTextArea.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    try {
                        currentTextArea.viewToModel2D(e.getPoint());
                        String clickedLink = findClickedLink(currentTextArea, e.getPoint());
                        System.out.println(clickedLink);
                        if (clickedLink != null) {
                            String fileName = links.get(clickedLink);
                            File file = new File(fileName);
                            if (file.exists()) {
                                Desktop.getDesktop().open(file);
                            } else {
                                JOptionPane.showMessageDialog(frame, "文件不存在: " + file.getAbsolutePath());
                            }
                        }
                    } catch (BadLocationException | IOException ex) {
                        JOptionPane.showMessageDialog(frame, "错误: " + ex.getMessage());
                    }
                }
            });
        }
        textArea.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                try {
                    textArea.viewToModel2D(e.getPoint());
                    String clickedLink = findClickedLink(textArea, e.getPoint());
                    if (clickedLink != null) {
                        String fileName = links.get(clickedLink);
                        File file = new File(fileName);
                        if (file.exists()) {
                            Desktop.getDesktop().open(file);
                        } else {
                            JOptionPane.showMessageDialog(frame, "文件不存在: " + file.getAbsolutePath());
                        }
                    }
                } catch (BadLocationException | IOException ex) {
                    JOptionPane.showMessageDialog(frame, "错误: " + ex.getMessage());
                }
            }
        });
        myList.addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting()) {
                String selected = myList.getSelectedValue();
                setSelectedValue(selected);
                currentTextArea = getTextAreaForPanel(selected);
                String[] messages = controller.getMessages(username, selected);
                for (String s : messages) {
                    String[] ms = s.split(":");
                    if (ms.length == 3) {
                        String ms1 = ms[0];
                        String ms2 = ms[1];
                        String ms3 = ms[2];
                        if (ms1.equals(username)) {
                            appendMessage(username + ":" + ms3 + ":" + selectedValue);
                        }
                        if ((ms2.equals(username))) {
                            appendMessage(selectedValue + ":" + ms3 + ":" + username);
                        }
                    }
                    if (ms.length == 4) {
                        String ms1 = ms[0];
                        String ms2 = ms[1];
                        String ms3 = ms[2];
                        String ms4 = ms[3];
                        if (ms1.equals(username)) {
                            appendMessage(username + ":" + ms3 + ":" + ms4);
                        }
                        if ((ms2.equals(username))) {
                            appendMessage(selectedValue + ":" + ms3 + ":" + ms4);
                        }
                    }
                }
                cardLayout.show(cardPanel, selected);
                jTextArea.setText(selectedValue);
                updateFileList();
            }
        });
        groupList.addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting()) {
                String selected = groupList.getSelectedValue();
                setSelectedValue(selected);
                String[] allGroupMessages = groupMessageController.getAllGroupMessages(selectedValue);
                for (String s : allGroupMessages) {
                    s = s + ":" + selected + ":" + "group";
                    appendMessage(s);
                }
                currentTextArea = getTextAreaForPanel(selected);
                cardLayout.show(cardPanel, selected);
                jTextArea.setText(selectedValue);
            }
            updateFileList();
        });
        btn_start.addActionListener(e -> {
            if (!flag) {
                flag = true;
                startClient();
            } else {
                try {
                    if (_self == null) {
                        _self = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8899));
                        _self.configureBlocking(false);
                        _self.register(selector, SelectionKey.OP_READ);
                        _self.write(charset.encode(username + " " + "上线了！"));
                        JOptionPane.showMessageDialog(null, "服务器连接成功");
                    } else {
                        JOptionPane.showMessageDialog(null, "服务器已连接");
                    }
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, "服务器连接失败");
                }
            }
        });
        // 发送按钮事件监听
        btn_send.addActionListener(e -> {
            SilenceUserController silenceUserController = new SilenceUserController();
            String[] silenceUser = silenceUserController.getSilenceUser();
            for (String s : silenceUser) {
                if (s.equals(username)) {
                    JOptionPane.showMessageDialog(null, "你被禁言了，无法发送消息");
                    return;
                }
            }
            String string;
            if (selectedValue != null) {
                if (groupModel.contains(selectedValue)) {
                    string = textField.getText().trim() + ":" + selectedValue + ":" + "group";
                } else {
                    string = textField.getText().trim() + ":" + selectedValue;
                }
            } else {
                string = textField.getText().trim();
            }
            if (_self != null) {
                sendMessage(string);
                textField.setText("");
            } else {
                JOptionPane.showMessageDialog(null, "用户未连接服务器，无法发送信息");
            }
        });
        // 文本框回车事件监听
        textField.addActionListener(e -> {
            SilenceUserController silenceUserController = new SilenceUserController();
            String[] silenceUser = silenceUserController.getSilenceUser();
            for (String s : silenceUser) {
                if (s.equals(username)) {
                    JOptionPane.showMessageDialog(null, "你被禁言了，无法发送消息");
                    return;
                }
            }
            String string;
            if (selectedValue != null) {
                if (groupModel.contains(selectedValue)) {
                    string = textField.getText().trim() + ":" + selectedValue + ":" + "group";
                } else {
                    string = textField.getText().trim() + ":" + selectedValue;
                }
            } else {
                string = textField.getText().trim();
            }
            if (_self != null) {
                sendMessage(string);
                textField.setText("");
            } else {
                JOptionPane.showMessageDialog(null, "用户未连接服务器，无法发送信息");
            }
        });
        btn_config.addActionListener(e -> {
            if (fileSelectedValue != null) {
                openFile();
            } else {
                JOptionPane.showMessageDialog(null, "未选择文件");
            }
        });
        //添加好友事件监听
        button1.addActionListener(e -> {
            AddUserView addUserView = new AddUserView(username);
            addUserView.showUi();
        });
        button2.addActionListener(e -> updateFileList());
        btn_flush.addActionListener(e -> {
            if (selectedValue != null) {
                updateGroupList();
                updateUserList();
                updateOnlineUsers();
                cardLayout.show(cardPanel, "main");
            } else {
                updateUserList();
                updateGroupList();
                updateOnlineUsers();
            }
        });
        //删除好友事件
        btn_delete.addActionListener(e -> {
            DeleteUserView deleteUserView = new DeleteUserView(username);
            deleteUserView.showUi();
        });
    }

    private JTextPane getTextAreaForPanel(String selected) {
        JTextPane jTextArea = new JTextPane();
        JScrollPane jScrollPane = new JScrollPane(jTextArea);
        jTextArea.setEditable(false);
        jScrollPane.setBorder(new TitledBorder("消息区"));
        cardPanel.add(jScrollPane, selected);
        return jTextArea;
    }

    private void stopClient() {
        try {
            if (_self != null) {
                _self.write(charset.encode(username + ":" + "下线了"));
            }
        } catch (IOException e) {
            appendMessage("断开连接时发生异常");
        }
    }

    private void startClient() {
        try {
            if (_self != null) {
                JOptionPane.showMessageDialog(null, "服务器已连接");
            } else {
                selector = Selector.open();
                _self = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8899));
                _self.configureBlocking(false);
                _self.register(selector, SelectionKey.OP_READ);
                _self.write(charset.encode(username + " " + "上线了！"));
                JOptionPane.showMessageDialog(null, "服务器连接成功");
                MainMessageController mainMessageController = new MainMessageController();
                String[] messages1 = mainMessageController.getMessages();
                for (String s : messages1) {
                    appendMessage(s);
                }
                String[] messages2 = mainMessageController.getMessages();
                for (String message : messages2) {
                    String[] split = message.split(":");
                    if (split.length == 4) {
                        fileModel.addElement(split[1] + ":" + split[2]);
                    }
                }
                // 启动接收消息线程
                thread = new Thread(new ReceiveThread());
                thread.start();
            }
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, "服务器连接失败");
        }
    }

    private void updateFileList() {
        SwingUtilities.invokeLater(() -> {
            fileModel.clear();
            if (selectedValue == null) {
                for (String fileName : mainMessageController.getMessages()) {
                    String[] ms = fileName.split(":");
                    if (ms.length == 4) {
                        fileModel.addElement(ms[1] + ":" + ms[2]);
                    }
                }
            } else {
                if (groupModel.contains(selectedValue)) {
                    for (String fileName : groupMessageController.getAllGroupMessages(selectedValue)) {
                        String[] ms = fileName.split(":");
                        if (ms.length == 3) {
                            fileModel.addElement(ms[1] + ":" + ms[2]);
                        }
                    }
                } else {
                    for (String fileName : controller.getMessages(username, selectedValue)) {
                        String[] ms = fileName.split(":");
                        if (ms.length == 4) {
                            fileModel.addElement(ms[2] + ":" + ms[3]);
                        }
                    }
                }
            }
        });
    }

    private void sendMessage(String message) {
        if (message.isEmpty()) {
            return;
        }
        try {
            message = username + ":" + message;
            _self.write(charset.encode(message));
            if (selectedValue == null || groupModel.contains(selectedValue)) {
                return;
            }
            appendMessage(message);
        } catch (IOException e) {
            appendMessage("发送消息失败");
        }
    }

    // 查找被点击的链接文本
    private static String findClickedLink(JTextComponent textComponent, Point point) throws BadLocationException {
        for (String linkText : links.keySet()) {
            int start = textComponent.getDocument().getText(0, textComponent.getDocument().getLength()).indexOf(linkText);
            if (start != -1) {
                Rectangle startRect = textComponent.modelToView(start);
                Rectangle endRect = textComponent.modelToView(start + linkText.length());
                if (startRect != null && endRect != null) {
                    Rectangle linkRect = startRect.union(endRect);
                    if (linkRect.contains(point)) {
                        return linkText;
                    }
                }
            }
        }
        return null;
    }

    private void appendMessage(String message) {
        StyledDocument doc = textArea.getStyledDocument();
        Style boldStyle = doc.addStyle("bold", null);
        StyleConstants.setFontFamily(boldStyle, "宋体");
        StyleConstants.setFontSize(boldStyle, 15);
        StyleConstants.setBold(boldStyle, true);

        Style plainStyle = doc.addStyle("plain", null);
        StyleConstants.setFontFamily(plainStyle, "黑体");
        StyleConstants.setFontSize(plainStyle, 15);
        StyleConstants.setBold(plainStyle, false);
        StyleConstants.setForeground(plainStyle, Color.BLUE);

        Runnable updateUI = () -> {
            String[] parts = message.split(":");
            if (parts.length == 1) {
                String[] m = message.split(" ");
                if (m.length > 1 && "上线了！".equals(m[1])) {
                    return;
                }
            } else if (parts.length == 2) {
                if ("下线了".equals(parts[1])) {
                    return;
                } else {
                    try {
                        doc.insertString(doc.getLength(), message + "\n", boldStyle);
                    } catch (BadLocationException e) {
                        throw new RuntimeException(e);
                    }
                    textArea.setCaretPosition(textArea.getDocument().getLength());
                }
            } else if (parts.length == 3) {
                if ("C".equals(parts[1]) || "D".equals(parts[1]) || "E".equals(parts[1])) {
                    try {
                        doc.insertString(doc.getLength(), message + "\n", plainStyle);
                    } catch (BadLocationException e) {
                        throw new RuntimeException(e);
                    }
                    textArea.setCaretPosition(textArea.getDocument().getLength());
                }
                if ("0".equals(parts[2])) {
                    try {
                        doc.insertString(doc.getLength(), parts[0] + ":" + parts[1] + "\n", boldStyle);
                    } catch (BadLocationException e) {
                        throw new RuntimeException(e);
                    }
                }
            } else if (parts.length == 4) {
                if (!parts[3].equals("1")) {
                    return;
                }
                if ("C".equals(parts[1]) || "D".equals(parts[1]) || "E".equals(parts[1])) {
                    try {
                        doc.insertString(doc.getLength(), parts[0] + ":" + parts[1] + ":" + parts[2] + "\n", plainStyle);
                    } catch (BadLocationException e) {
                        throw new RuntimeException(e);
                    }
                    textArea.setCaretPosition(textArea.getDocument().getLength());
                }
            } else if (parts.length == 5) {
                return;
            } else {
                try {
                    doc.insertString(doc.getLength(), message + "\n", boldStyle);
                } catch (BadLocationException e) {
                    throw new RuntimeException(e);
                }
                textArea.setCaretPosition(textArea.getDocument().getLength());
            }
        };

        if (selectedValue != null) {
            SwingUtilities.invokeLater(() -> {
                System.out.println(message);
                StyledDocument currentDoc = currentTextArea.getStyledDocument();
                Style currentBoldStyle = currentDoc.addStyle("bold", null);
                StyleConstants.setFontFamily(currentBoldStyle, "宋体");
                StyleConstants.setFontSize(currentBoldStyle, 15);
                StyleConstants.setBold(currentBoldStyle, true);

                Style currentPlainStyle = currentDoc.addStyle("plain", null);
                StyleConstants.setFontFamily(currentPlainStyle, "黑体");
                StyleConstants.setFontSize(currentPlainStyle, 15);
                StyleConstants.setBold(currentPlainStyle, false);
                StyleConstants.setForeground(currentPlainStyle, Color.BLUE);
                String[] parts = message.split(":");
                if (parts.length == 1) {
                    String[] m = message.split(" ");
                    if (m.length > 1 && "上线了！".equals(m[1])) {
                        return;
                    }
                } else if (parts.length == 2) {
                    if ("下线了".equals(parts[1])) {
                        return;
                    } else {
                        try {
                            doc.insertString(doc.getLength(), message + "\n", boldStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                } else if (parts.length == 3) {
                    if ((username.equals(parts[0]) && selectedValue.equals(parts[2])) || (username.equals(parts[2]) && selectedValue.equals(parts[0]))) {
                        try {
                            currentDoc.insertString(currentDoc.getLength(), parts[0] + ":" + parts[1] + "\n", currentBoldStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    if ("C".equals(parts[1]) || "D".equals(parts[1]) || "E".equals(parts[1])) {
                        try {
                            currentDoc.insertString(currentDoc.getLength(), message + "\n", currentPlainStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                        currentTextArea.setCaretPosition(currentTextArea.getDocument().getLength());
                    }
                }
                if (parts.length == 4) {
                    if (parts[3].equals("1")) {
                        try {
                            doc.insertString(doc.getLength(), parts[0] + ":" + parts[1] + ":" + parts[2] + "\n", plainStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    if (parts[3].equals("group") && parts[2].equals(selectedValue)) {
                        try {
                            currentDoc.insertString(currentDoc.getLength(), parts[0] + ":" + parts[1] + "\n", boldStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    if (parts[3].equals(selectedValue) || parts[3].equals(username)) {
                        try {
                            currentDoc.insertString(currentDoc.getLength(), parts[0] + ":" + parts[1] + ":" + parts[2] + "\n", plainStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                } else if (parts.length == 5) {
                    if (parts[3].equals(selectedValue) && parts[4].equals("group")) {
                        try {
                            currentDoc.insertString(currentDoc.getLength(), parts[0] + ":" + parts[1] + ":" + parts[2] + "\n", plainStyle);
                        } catch (BadLocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            });
        } else {
            SwingUtilities.invokeLater(updateUI);
        }
    }

    private class ReceiveThread implements Runnable {
        @Override
        public void run() {
            while (running) {
                try {
                    selector.select();
                    updateOnlineUsers();
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (key.isConnectable()) {
                            SocketChannel channel = (SocketChannel) key.channel();
                            if (channel.isConnectionPending()) {
                                channel.finishConnect();
                            }
                            channel.register(selector, SelectionKey.OP_READ);
                            channel.write(charset.encode(username + " 上线了！"));
                        } else if (key.isReadable()) {
                            SocketChannel client = (SocketChannel) key.channel();
                            buffer.clear();
                            int count = client.read(buffer);
                            if (count > 0) {
                                buffer.flip();
                                String receivedMsg = charset.decode(buffer).toString();
                                String s = ":";
                                String[] ms = receivedMsg.split(s);
                                if (ms.length == 2) {
                                    String ms1 = ms[0];
                                    String ms2 = ms[1];
                                    if (ms1.equals(username) && ms2.equals("下线了")) {
                                        _self = null;
                                        if (flag1) {
                                            if (ChatServer.flag2) {
                                                JOptionPane.showMessageDialog(null, "你被管理员强制下线了");
                                                running = false;
                                                frame.dispose();
                                            } else {
                                                setAllUsersOffline();
                                            }
                                        } else {
                                            ChatServer.onlineUsers.remove(username);
                                        }
                                    } else {
                                        appendMessage(receivedMsg);
                                    }
                                } else {
                                    appendMessage(receivedMsg);
                                }
                            }
                        }
                    }
                } catch (IOException e) {
                    JOptionPane.showMessageDialog(null, "服务器连接失败");
                    break;
                }
            }
        }
    }

    private void updateUserList() {
        SwingUtilities.invokeLater(() -> {
            model.clear();
            List<String> strings = chatClientController.selectUsers(username);
            for (String user : strings) {
                model.addElement(user);
            }
        });
    }

    private void updateGroupList() {
        SwingUtilities.invokeLater(() -> {
            groupModel.clear();
            String[] userGroups = groupChatController.getUserGroups(username);
            for (String userGroup : userGroups) {
                groupModel.addElement(userGroup);
            }
        });
    }

    public void setSelectedValue(String s) {
        selectedValue = s;
    }

    private void openFile() {
        File file = new File(fileSelectedValue);
        if (file.exists()) {
            try {
                Desktop.getDesktop().open(file);
            } catch (IOException e) {
                JOptionPane.showMessageDialog(null, "文件打开失败");
            }
        } else {
            JOptionPane.showMessageDialog(frame, "文件不存在: " + file.getAbsolutePath());
        }
    }

    private void updateOnlineUsers() {
        SwingUtilities.invokeLater(() -> {
            Set<String> strings1 = ChatServer.onlineUsers.keySet();
            for (String s : strings1) {
                if (model.contains(s)) {
                    onlineUsers.put(s, true);
                }
            }
            myList.repaint();
        });
    }

    private void setAllUsersOffline() {
        Map<String, Boolean> updatedUsers = new HashMap<>();
        for (String user : onlineUsers.keySet()) {
            updatedUsers.put(user, false);
        }
        onlineUsers.putAll(updatedUsers);
        myList.repaint();
    }

    private static class OnlineUserListCellRenderer extends DefaultListCellRenderer {
        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            String userName = (String) value;
            Boolean isOnline = onlineUsers.get(userName);  // 获取用户的在线状态

            if (isOnline != null && isOnline) {
                c.setForeground(Color.BLACK);  // 在线用户的文字颜色为黑色
            } else {
                c.setForeground(Color.GRAY);    // 离线或未知用户的文字颜色为灰色
            }

            return c;
        }
    }

    public static void main(String[] args) {
        new ChatClient("123456");
    }
}